home *** CD-ROM | disk | FTP | other *** search
/ AGA Toolkit '97 / The AGA Toolkit '97.iso / miscellaneous / science / maths / calc / source / string.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-07  |  6.9 KB  |  293 lines

  1. /*
  2.  * Copyright (c) 1994 David I. Bell
  3.  * Permission is granted to use, distribute, or modify this source,
  4.  * provided that this copyright notice remains intact.
  5.  *
  6.  * String list routines.
  7.  */
  8.  
  9. #include "calc.h"
  10. #include "string.h"
  11.  
  12. #define STR_TABLECHUNK    100    /* how often to reallocate string table */
  13. #define STR_CHUNK    2000    /* size of string storage allocation */
  14. #define STR_UNIQUE    100    /* size of string to allocate separately */
  15.  
  16.  
  17. static char *chartable;        /* single character string table */
  18.  
  19. static struct {
  20.     long l_count;        /* count of strings in table */
  21.     long l_maxcount;    /* maximum strings storable in table */
  22.     long l_avail;        /* characters available in current string */
  23.     char *l_alloc;        /* next available string storage */
  24.     char **l_table;        /* current string table */
  25. } literals;
  26.  
  27.  
  28. /*
  29.  * Initialize or reinitialize a string header for use.
  30.  */
  31. void
  32. initstr(hp)
  33.     register STRINGHEAD *hp;    /* structure to be inited */
  34. {
  35.     if (hp->h_list == NULL) {
  36.         hp->h_list = (char *)malloc(2000);
  37.         hp->h_avail = 2000;
  38.         hp->h_used = 0;
  39.     }
  40.     hp->h_avail += hp->h_used;
  41.     hp->h_used = 0;
  42.     hp->h_count = 0;
  43.     hp->h_list[0] = '\0';
  44.     hp->h_list[1] = '\0';
  45. }
  46.  
  47.  
  48. /*
  49.  * Copy a string to the end of a list of strings, and return the address
  50.  * of the copied string.  Returns NULL if the string could not be copied.
  51.  * No checks are made to see if the string is already in the list.
  52.  * The string cannot be null or have imbedded nulls.
  53.  */
  54. char *
  55. addstr(hp, str)
  56.     register STRINGHEAD *hp;    /* header of string storage */
  57.     char *str;        /* string to be added */
  58. {
  59.     char *retstr;        /* returned string pointer */
  60.     char *list;        /* string list */
  61.     long newsize;        /* new size of string list */
  62.     long len;        /* length of current string */
  63.  
  64.     if ((str == NULL) || (*str == '\0'))
  65.         return NULL;
  66.     len = strlen(str) + 1;
  67.     if (hp->h_avail <= len) {
  68.         newsize = len + 2000 + hp->h_used + hp->h_avail;
  69.         list = (char *)realloc(hp->h_list, newsize);
  70.         if (list == NULL)
  71.             return NULL;
  72.         hp->h_list = list;
  73.         hp->h_avail = newsize - hp->h_used;
  74.     }
  75.     retstr = hp->h_list + hp->h_used;
  76.     hp->h_used += len;
  77.     hp->h_avail -= len;
  78.     hp->h_count++;
  79.     strcpy(retstr, str);
  80.     retstr[len] = '\0';
  81.     return retstr;
  82. }
  83.  
  84.  
  85. /*
  86.  * Return a null-terminated string which consists of a single character.
  87.  * The table is initialized on the first call.
  88.  */
  89. char *
  90. charstr(ch)
  91.     int ch;
  92. {
  93.     char *cp;
  94.     int i;
  95.  
  96.     if (chartable == NULL) {
  97.         cp = (char *)malloc(512);
  98.         if (cp == NULL)
  99.             math_error("Cannot allocate character table");
  100.         for (i = 0; i < 256; i++) {
  101.             *cp++ = (char)i;
  102.             *cp++ = '\0';
  103.         }
  104.         chartable = cp - 512;
  105.     }
  106.     return &chartable[(ch & 0xff) * 2];
  107. }
  108.  
  109.  
  110. /*
  111.  * Find a string with the specified name and return its number in the
  112.  * string list.  The first string is numbered zero.  Minus one is returned
  113.  * if the string is not found.
  114.  */
  115. long
  116. findstr(hp, str)
  117.     STRINGHEAD *hp;        /* header of string storage */
  118.     register char *str;    /* string to be added */
  119. {
  120.     register char *test;    /* string being tested */
  121.     long len;        /* length of string being found */
  122.     long testlen;        /* length of test string */
  123.     long index;        /* index of string */
  124.  
  125.     if ((hp->h_count <= 0) || (str == NULL))
  126.         return -1;
  127.     len = strlen(str);
  128.     test = hp->h_list;
  129.     index = 0;
  130.     while (*test) {
  131.         testlen = strlen(test);
  132.         if ((testlen == len) && (*test == *str) && (strcmp(test, str) == 0))
  133.             return index;
  134.         test += (testlen + 1);
  135.         index++;
  136.     }
  137.     return -1;
  138. }
  139.  
  140.  
  141. /*
  142.  * Return the name of a string with the given index.
  143.  * If the index is illegal, a pointer to an empty string is returned.
  144.  */
  145. char *
  146. namestr(hp, n)
  147.     STRINGHEAD *hp;        /* header of string storage */
  148.     long n;
  149. {
  150.     register char *str;    /* current string */
  151.  
  152.     if ((unsigned long)n >= hp->h_count)
  153.         return "";
  154.     str = hp->h_list;
  155.     while (*str) {
  156.         if (--n < 0)
  157.             return str;
  158.         str += (strlen(str) + 1);
  159.     }
  160.     return "";
  161. }
  162.  
  163.  
  164. /*
  165.  * Useful routine to return the index of one string within another one
  166.  * which has the format:  "str1\000str2\000str3\000...strn\0\0".  Index starts
  167.  * at one for the first string.  Returns zero if the string being checked
  168.  * is not contained in the formatted string.
  169.  *
  170.  * Be sure to use \000 instead of \0.  ANSI-C compilers interpret "foo\0foo..."
  171.  * as "foo\017oo...".
  172.  */
  173. long
  174. stringindex(format, test)
  175.     register char *format;    /* string formatted into substrings */
  176.     char *test;        /* string to be found in formatted string */
  177. {
  178.     long index;        /* found index */
  179.     long len;        /* length of current piece of string */
  180.     long testlen;        /* length of test string */
  181.  
  182.     testlen = strlen(test);
  183.     index = 1;
  184.     while (*format) {
  185.         len = strlen(format);
  186.         if ((len == testlen) && (*format == *test) &&
  187.             (strcmp(format, test) == 0))
  188.                 return index;
  189.         format += (len + 1);
  190.         index++;
  191.     }
  192.     return 0;
  193. }
  194.  
  195.  
  196. /*
  197.  * Add a possibly new literal string to the literal string pool.
  198.  * Returns the new string address which is guaranteed to be always valid.
  199.  * Duplicate strings will repeatedly return the same address.
  200.  */
  201. char *
  202. addliteral(str)
  203.     char *str;
  204. {
  205.     register char **table;    /* table of strings */
  206.     char *newstr;        /* newly allocated string */
  207.     long count;        /* number of strings */
  208.     long len;        /* length of string to allocate */
  209.  
  210.     len = strlen(str);
  211.     if (len <= 1)
  212.         return charstr(*str);
  213.     /*
  214.      * See if the string is already in the table.
  215.      */
  216.     table = literals.l_table;
  217.     count = literals.l_count;
  218.     while (count-- > 0) {
  219.         if ((str[0] == table[0][0]) && (str[1] == table[0][1]) &&
  220.             (strcmp(str, table[0]) == 0))
  221.                 return table[0];
  222.         table++;
  223.     }
  224.     /*
  225.      * Make the table of string pointers larger if necessary.
  226.      */
  227.     if (literals.l_count >= literals.l_maxcount) {
  228.         count = literals.l_maxcount + STR_TABLECHUNK;
  229.         if (literals.l_maxcount)
  230.             table = (char **) realloc(literals.l_table, count * sizeof(char *));
  231.         else
  232.             table = (char **) malloc(count * sizeof(char *));
  233.         if (table == NULL)
  234.             math_error("Cannot allocate string literal table");
  235.         literals.l_table = table;
  236.         literals.l_maxcount = count;
  237.     }
  238.     table = literals.l_table;
  239.     /*
  240.      * If the new string is very long, allocate it manually.
  241.      */
  242.     len = (len + 2) & ~1;    /* add room for null and round up to word */
  243.     if (len >= STR_UNIQUE) {
  244.         newstr = (char *)malloc(len);
  245.         if (newstr == NULL)
  246.             math_error("Cannot allocate large literal string");
  247.         strcpy(newstr, str);
  248.         table[literals.l_count++] = newstr;
  249.         return newstr;
  250.     }
  251.     /*
  252.      * If the remaining space in the allocate string is too small,
  253.      * then allocate a new one.
  254.      */
  255.     if (literals.l_avail < len) {
  256.         newstr = (char *)malloc(STR_CHUNK);
  257.         if (newstr == NULL)
  258.             math_error("Cannot allocate new literal string");
  259.         literals.l_alloc = newstr;
  260.         literals.l_avail = STR_CHUNK;
  261.     }
  262.     /*
  263.      * Allocate the new string from the allocate string.
  264.      */
  265.     newstr = literals.l_alloc;
  266.     literals.l_avail -= len;
  267.     literals.l_alloc += len;
  268.     table[literals.l_count++] = newstr;
  269.     strcpy(newstr, str);
  270.     return newstr;
  271. }
  272.  
  273.  
  274. /*
  275.  * Calculate a trivial hash value for a string.
  276.  */
  277. HASH
  278. hashstr(cp)
  279.     char *cp;
  280. {
  281.     int len;
  282.     HASH hash;
  283.  
  284.     len = strlen(cp);
  285.     hash = len * 300007;
  286.     while (len-- > 0)
  287.         /* ignore Saber-C warning about Over/underflow */
  288.         hash = hash * 300017 + *cp++ + 300043;
  289.     return hash;
  290. }
  291.  
  292. /* END CODE */
  293.